from flask import Flask, render_template, url_for, redirect, flash, request
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, RadioField, IntegerField, SelectField, FloatField
from wtforms.validators import DataRequired, Email, EqualTo, Length, ValidationError, NumberRange
from functools import wraps  # 添加这一行导入wraps

# 导入数据库模型
from models import db, User, HealthKnowledge, Post, Comment  # 添加所需的模型

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 初始化数据库
db.init_app(app)

# 登录管理器
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

# 登录表单
class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired()])
    password = PasswordField('密码', validators=[DataRequired()])
    remember_me = BooleanField('记住我')
    submit = SubmitField('登录')

# 注册表单
class RegistrationForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(max=20)])
    email = StringField('电子邮箱', validators=[DataRequired(), Email()])
    phone = StringField('手机号码', validators=[
                        DataRequired(), Length(min=11, max=11)])
    password = PasswordField('密码', validators=[DataRequired(), Length(min=6)])
    confirm_password = PasswordField(
        '确认密码', validators=[DataRequired(), EqualTo('password')])
    admin_key = StringField('管理员密钥（可选）')
    submit = SubmitField('注册')

    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('该用户名已被使用，请选择其他用户名。')

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('该邮箱已被注册，请使用其他邮箱。')



# 用户信息表单
class UserInfoForm(FlaskForm):
    username = StringField('用户名', render_kw={'readonly': True})
    email = StringField('电子邮箱', validators=[DataRequired(), Email()])
    phone = StringField('手机号码', validators=[
                        DataRequired(), Length(min=11, max=11)])
    gender = RadioField(
        '性别', choices=[('男', '男'), ('女', '女')], validators=[DataRequired()])
    age = IntegerField('年龄', validators=[NumberRange(min=1, max=120)])
    height = FloatField('身高', validators=[NumberRange(min=50, max=250)])
    weight = FloatField('体重', validators=[NumberRange(min=20, max=300)])
    goal = SelectField('健康目标', choices=[
        ('减肥', '减肥'),
        ('增肌', '增肌'),
        ('增肌减脂', '增肌减脂'),
        ('保持健康', '保持健康'),
        ('提高耐力', '提高耐力'),
        ('其他', '其他')
    ])
    submit = SubmitField('保存修改')

# 路由
@app.route('/')
def index():
    # 如果是管理员，直接重定向到管理员仪表盘
    if current_user.is_authenticated and current_user.is_admin:
        return redirect(url_for('admin_dashboard'))
    # 普通用户或未登录用户看到普通首页
    return render_template('index.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('index'))

    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember_me.data)
            next_page = request.args.get('next')
            return redirect(next_page or url_for('index'))
        flash('用户名或密码错误')
    return render_template('login.html', form=form)


@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))


@app.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('index'))

    form = RegistrationForm()
    if form.validate_on_submit():
        try:
            # 创建新用户
            user = User(username=form.username.data,
                        email=form.email.data, phone_number=form.phone.data)
            user.set_password(form.password.data)

            # 检查管理员密钥
            admin_key = form.admin_key.data
            if admin_key == "ADMIN_KEY_2025":  # 设置固定的管理员密钥
                user.is_admin = True
                print(f"用户 {form.username.data} 使用管理员密钥注册")

            db.session.add(user)
            db.session.commit()

            # 验证用户是否成功保存
            saved_user = User.query.filter_by(
                username=form.username.data).first()
            if saved_user:
                print(f"用户 {saved_user.username} 已成功保存到数据库")
                if saved_user.is_admin:
                    flash('注册成功！您已被授予管理员权限。请登录')
                else:
                    flash('注册成功！请登录')
                return redirect(url_for('login'))
            else:
                print("用户保存失败，但没有抛出异常")
                flash('注册失败，请重试')
        except Exception as e:
            db.session.rollback()
            print(f"注册过程中发生错误: {str(e)}")
            flash(f'注册过程中发生错误: {str(e)}')
    else:
        # 如果表单验证失败，打印错误信息
        if form.errors:
            print(f"表单验证错误: {form.errors}")
            # 添加这一行，将表单验证错误显示给用户
            for field, errors in form.errors.items():
                for error in errors:
                    flash(f'{form[field].label.text}: {error}', 'error')

    return render_template('register.html', form=form)


@app.route('/user-info', methods=['GET', 'POST'])
@login_required
def user_info():
    form = UserInfoForm()

    if request.method == 'GET':
        # 预填表单
        form.username.data = current_user.username
        form.email.data = current_user.email
        form.phone.data = current_user.phone_number
        form.gender.data = current_user.gender
        form.age.data = current_user.age
        form.height.data = current_user.height
        form.weight.data = current_user.weight
        form.goal.data = current_user.goal

    return render_template('user-info.html', form=form, user_data=current_user)


@app.route('/update-user-info', methods=['POST'])
@login_required
def update_user_info():
    form = UserInfoForm()
    if form.validate_on_submit():
        try:
            # 检查邮箱是否已被其他用户使用
            existing_user = User.query.filter(
                User.email == form.email.data, User.id != current_user.id).first()
            if existing_user:
                flash('该邮箱已被其他用户使用，请使用其他邮箱。', 'error')
                return redirect(url_for('user_info'))

            # 更新用户信息
            current_user.email = form.email.data
            current_user.phone_number = form.phone.data
            current_user.gender = form.gender.data
            current_user.age = form.age.data
            current_user.height = form.height.data
            current_user.weight = form.weight.data
            current_user.goal = form.goal.data

            # 确保提交到数据库
            db.session.commit()

            flash('个人信息更新成功！')
        except Exception as e:
            db.session.rollback()
            flash(f'更新个人信息时发生错误: {str(e)}', 'error')

        return redirect(url_for('user_info'))

    # 表单验证失败时，显示错误信息
    for field, errors in form.errors.items():
        for error in errors:
            flash(f'{getattr(form, field).label.text}: {error}', 'error')

    return redirect(url_for('user_info'))


@app.route('/health-plan')
@login_required
def health_plan():
    # 直接重定向到健康计划推荐页面
    return render_template('health-plan-recommendation.html')


@app.route('/knowledge')
def knowledge():
    return render_template('knowledge.html')


@app.route('/health-knowledge')
def health_knowledge():
    # 获取分类参数
    category = request.args.get('category')
    page = request.args.get('page', 1, type=int)
    per_page = 6  # 每页显示6篇文章

    # 构建查询
    query = HealthKnowledge.query

    # 如果有分类参数，按分类筛选
    if category:
        query = query.filter_by(category=category)

    # 按创建时间降序排序并分页
    pagination = query.order_by(HealthKnowledge.created_at.desc()).paginate(
        page=page, per_page=per_page, error_out=False)
    articles = pagination.items


    return render_template('health-knowledge.html',
                           articles=articles,
                           pagination=pagination,
                           category=category)


@app.route('/health-knowledge/<int:article_id>')
def article_detail(article_id):
    article = HealthKnowledge.query.get_or_404(article_id)

    # 增加浏览量
    article.view_count += 1
    db.session.commit()

    return render_template('article-detail.html', article=article)


@app.route('/search-knowledge')
def search_knowledge():
    keyword = request.args.get('keyword', '')
    page = request.args.get('page', 1, type=int)
    per_page = 6

    # 构建搜索查询
    query = HealthKnowledge.query.filter(
        HealthKnowledge.title.contains(keyword) |
        HealthKnowledge.content.contains(keyword)
    )

    # 分页
    pagination = query.order_by(HealthKnowledge.created_at.desc()).paginate(
        page=page, per_page=per_page, error_out=False)
    articles = pagination.items

    # 获取一篇精选文章
    featured_article = HealthKnowledge.query.order_by(
        HealthKnowledge.view_count.desc()).first()

    return render_template('health-knowledge.html',
                           articles=articles,
                           pagination=pagination,
                           featured_article=featured_article,
                           keyword=keyword)


@app.route('/community')
def community():
    # 获取所有帖子，按创建时间倒序排列
    posts = Post.query.order_by(Post.created_at.desc()).all()
    return render_template('community.html', posts=posts)


@app.route('/community/post/<int:post_id>')
def post_detail(post_id):
    # 获取特定帖子及其评论
    post = Post.query.get_or_404(post_id)
    # 增加浏览次数
    post.view_count += 1
    db.session.commit()
    return render_template('post-detail.html', post=post)


@app.route('/create-post', methods=['GET', 'POST'])
@login_required
def create_post():
    if request.method == 'POST':
        title = request.form.get('title')
        content = request.form.get('content')

        post = Post(
            user_id=current_user.id,
            title=title,
            content=content
        )

        db.session.add(post)
        db.session.commit()

        flash('帖子发布成功！')
        return redirect(url_for('community'))

    return render_template('create-post.html')


@app.route('/community/comment/<int:post_id>', methods=['POST'])
@login_required
def add_comment(post_id):
    content = request.form.get('content')
    if content:
        comment = Comment(
            post_id=post_id,
            user_id=current_user.id,
            content=content
        )
        db.session.add(comment)
        db.session.commit()
        flash('评论成功！')
    else:
        flash('评论内容不能为空！')

    return redirect(url_for('post_detail', post_id=post_id))


@app.route('/community/like/<int:post_id>', methods=['POST'])
@login_required
def like_post(post_id):
    post = Post.query.get_or_404(post_id)
    post.like_count += 1
    db.session.commit()
    return redirect(url_for('post_detail', post_id=post_id))


@app.route('/reset-password-request')
def reset_password_request():
    return render_template('reset_password_request.html')


# 创建数据库表
def create_tables():
    with app.app_context():
        db.create_all()


# 管理员权限检查装饰器
def admin_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated or not current_user.is_admin:
            flash('您没有管理员权限')
            return redirect(url_for('index'))
        return f(*args, **kwargs)
    return decorated_function


@app.route('/admin')
@login_required
@admin_required
def admin_dashboard():
    # 获取管理员仪表盘需要的统计数据
    user_count = User.query.count()
    post_count = Post.query.count()
    article_count = HealthKnowledge.query.count()

    return render_template('admin/dashboard.html',
                           user_count=user_count,
                           post_count=post_count,
                           article_count=article_count)


@app.route('/admin/users')
@login_required
@admin_required
def admin_users():
    # 获取搜索关键词
    keyword = request.args.get('keyword', '')

    # 根据关键词搜索用户
    if keyword:
        users = User.query.filter(
            (User.username.contains(keyword))
        ).all()
    else:
        users = User.query.all()

    return render_template('admin/users.html', users=users, keyword=keyword)


@app.route('/admin/posts')
@login_required
@admin_required
def admin_posts():
    # 获取关键字参数用于搜索
    keyword = request.args.get('keyword', '')
    if keyword:
        posts = Post.query.filter(Post.title.contains(keyword)).all()
    else:
        posts = Post.query.all()
    return render_template('admin/posts.html', posts=posts, keyword=keyword)


@app.route('/admin/delete-post/<int:post_id>', methods=['POST'])
@login_required
@admin_required
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    try:
        db.session.delete(post)
        db.session.commit()
        flash('帖子已成功删除')
    except Exception as e:
        db.session.rollback()
        flash(f'删除帖子时发生错误: {str(e)}', 'error')

    return redirect(url_for('admin_posts'))


# 健康知识管理
@app.route('/admin/knowledge')
@login_required
@admin_required
def admin_knowledge():
    # 获取关键字参数用于搜索
    keyword = request.args.get('keyword', '')
    if keyword:
        articles = HealthKnowledge.query.filter(
            HealthKnowledge.title.contains(keyword) |
            HealthKnowledge.content.contains(keyword)
        ).order_by(HealthKnowledge.created_at.desc()).all()
    else:
        articles = HealthKnowledge.query.order_by(
            HealthKnowledge.created_at.desc()).all()

    return render_template('admin/knowledge.html', articles=articles, keyword=keyword)

# 添加健康知识文章
@app.route('/admin/knowledge/add', methods=['GET', 'POST'])
@login_required
@admin_required
def admin_add_knowledge():
    if request.method == 'POST':
        title = request.form.get('title')
        content = request.form.get('content')
        category = request.form.get('category')

        if not title or not content or not category:
            flash('标题、内容和分类不能为空')
            return redirect(url_for('admin_add_knowledge'))

        try:
            article = HealthKnowledge(
                title=title,
                content=content,
                category=category,
                author=current_user.username,
                view_count=0
            )
            db.session.add(article)
            db.session.commit()
            flash('文章添加成功')
            return redirect(url_for('admin_knowledge'))
        except Exception as e:
            db.session.rollback()
            flash(f'添加文章时发生错误: {str(e)}', 'error')
            return redirect(url_for('admin_add_knowledge'))

    return render_template('admin/add_knowledge.html')

# 编辑健康知识文章
@app.route('/admin/knowledge/edit/<int:article_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def admin_edit_knowledge(article_id):
    article = HealthKnowledge.query.get_or_404(article_id)

    if request.method == 'POST':
        title = request.form.get('title')
        content = request.form.get('content')

        if not title or not content:
            flash('标题和内容不能为空')
            return redirect(url_for('admin_edit_knowledge', article_id=article_id))

        try:
            article.title = title
            article.content = content
            db.session.commit()
            flash('文章更新成功')
            return redirect(url_for('admin_knowledge'))
        except Exception as e:
            db.session.rollback()
            flash(f'更新文章时发生错误: {str(e)}', 'error')
            return redirect(url_for('admin_edit_knowledge', article_id=article_id))

    return render_template('admin/edit_knowledge.html', article=article)

# 删除健康知识文章
@app.route('/admin/knowledge/delete/<int:article_id>', methods=['POST'])
@login_required
@admin_required
def admin_delete_knowledge(article_id):
    article = HealthKnowledge.query.get_or_404(article_id)

    try:
        db.session.delete(article)
        db.session.commit()
        flash('文章已成功删除')
    except Exception as e:
        db.session.rollback()
        flash(f'删除文章时发生错误: {str(e)}', 'error')

    return redirect(url_for('admin_knowledge'))


# 重置用户密码
@app.route('/admin/reset-password/<int:user_id>', methods=['POST'])
@login_required
@admin_required
def reset_user_password(user_id):
    user = User.query.get_or_404(user_id)

    # 防止管理员重置其他管理员的密码
    if user.is_admin and user.id != current_user.id:
        flash('不能重置其他管理员的密码', 'warning')
        return redirect(url_for('admin_users'))

    try:
        # 重置密码为111111
        user.set_password('111111')
        db.session.commit()
        flash(f'已将用户 {user.username} 的密码重置为111111')
    except Exception as e:
        db.session.rollback()
        flash(f'重置密码时发生错误: {str(e)}', 'error')

    return redirect(url_for('admin_users'))

# 删除用户
@app.route('/admin/delete-user/<int:user_id>', methods=['POST'])
@login_required
@admin_required
def delete_user(user_id):
    user = User.query.get_or_404(user_id)


    try:
        # 先删除该用户的所有评论
        Comment.query.filter_by(user_id=user.id).delete()

        # 删除该用户的所有帖子
        Post.query.filter_by(user_id=user.id).delete()

        # 删除用户
        username = user.username
        db.session.delete(user)
        db.session.commit()
        flash(f'已成功删除用户 {username} 及其所有内容')
    except Exception as e:
        db.session.rollback()
        flash(f'删除用户时发生错误: {str(e)}', 'error')

    return redirect(url_for('admin_users'))


if __name__ == '__main__':
    create_tables()
    app.run(debug=True)
